package datagram;

import grouper.Util;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvException;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

public class Matchgram extends Datagram {
	public static final int METHOD = Imgproc.TM_CCOEFF_NORMED;
	public int 	method;
	public int	threshold;
	public Mat	full;
	public Mat	roi;
	
	public Matchgram( BufferedImage image ) {
		super(image);
	}
	
	public Matchgram( BufferedImage image, int threshold, int method ) {
		this(image);
		this.method = method;
		this.threshold = threshold;
		
		calculate();
	}
	
	@Override
	public double calculate() {
		if (!isLoaded()) {
			System.out.println("ERROR: could not prepare scalegram");
			return 0.0;
		}
		
		Mat cmat = Util.convert(image);
		
		// Build full image matrix
		full = new Mat(cmat.rows(), cmat.cols(), CvType.CV_32FC1);
		cmat.convertTo(full, CvType.CV_32FC1, 1.0/255);
		
		// Calculate ROI
		int roiMaxX = 0;
		int roiMaxY = 0;
		int roiMinX = image.getWidth();
		int roiMinY = image.getHeight();
		int color;
		
		for (int y = 0; y < image.getHeight(); y++) {
			for (int x = 0; x < image.getWidth(); x++) {
				color = image.getRGB(x,y) & 0x000000FF;
				//System.out.println(color);
				if (color < threshold) {
					if (x < roiMinX) roiMinX = x;
					if (y < roiMinY) roiMinY = y;
					if (x > roiMaxX) roiMaxX = x;
					if (y > roiMaxY) roiMaxY = y;
				}
			}
		}
		
		roi = full.submat(roiMinY, roiMaxY, roiMinX, roiMaxX);
		
		//System.out.println("FULL: " + full.cols() + "x" + full.rows());
		//System.out.println("ROI:  " + roi.cols() + "x" + roi.rows());
		//System.out.println();
		
		return 0.0;
	}
	
	@Override
	public double difference( Datagram datagram ) {
		if (!(datagram instanceof Matchgram))
			return 1.0;
		
		if (!isLoaded() || !datagram.isLoaded())
			return 1.0;
		
		Matchgram syutten = (Matchgram) datagram;
		double drow, dcol;
		
		// Syutten ROI is larger than group image
		if (roi.rows() > syutten.full.rows() || roi.cols() > syutten.full.cols())// ||
				//syutten.roi.rows() > full.rows() || syutten.roi.cols() > full.cols())
				return 1.0;
		
		drow = Math.abs(roi.rows() - syutten.roi.rows());
		dcol = Math.abs(roi.cols() - syutten.roi.cols());
		
		// Elements ROI are too different
		if (drow/syutten.roi.rows() > 0.1 ||
			dcol/syutten.roi.cols() > 0.1)
			return 1.0;
		
		Mat res2 = new Mat(full.rows(), full.cols(), CvType.CV_32FC1);
		Imgproc.matchTemplate(syutten.full, roi, res2, method);
		MinMaxLocResult loc2 = Core.minMaxLoc(res2);
		
		if (method == Imgproc.TM_CCOEFF_NORMED || method == Imgproc.TM_CCORR_NORMED)
			return 1 - (loc2.maxVal);
		
		return (loc2.minVal);
	}
	
	public void merge( Datagram datagram ) {
		if (!(datagram instanceof Matchgram) || !isLoaded() || !datagram.isLoaded())
			return;
	}
}
